package com.ly.heart.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.KingAllocateDetailEntity;
import com.ly.heart.domain.KingAllocateInfoEntity;
import com.ly.heart.domain.KingRealInventoryEntity;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.heart.mapper.KingAllocateInfoMapper;
import com.ly.heart.service.IActModelService;
import com.ly.heart.service.IKingAllocateInfoService;
import com.ly.heart.service.IKingRealInventoryService;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

/**
 * new调拨单Service业务层处理
 *
 * @author wutao
 * @date 2024-08-07
 */
@Service
public class KingAllocateInfoServiceImpl extends ServiceImpl<KingAllocateInfoMapper, KingAllocateInfoEntity> implements IKingAllocateInfoService {
    @Resource
    private KingAllocateInfoMapper erpKingAllocateInfoMapper;
    @Resource
    private KingAllocateDetailServiceImpl kingAllocateDetailService;
    @Resource
    private IKingRealInventoryService kingRealInventoryEntityService;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private IActModelService actModelService;

    /**
     * 查询new调拨单
     *
     * @param id new调拨单ID
     * @return new调拨单
     */
    @Override
    public KingAllocateInfoEntity selectErpKingAllocateInfoById(String id) {
        return erpKingAllocateInfoMapper.selectErpKingAllocateInfoById(id);
    }

    /**
     * 查询new调拨单列表
     *
     * @param erpKingAllocateInfo new调拨单
     * @return new调拨单
     */
    @Override
    public List<KingAllocateInfoEntity> selectErpKingAllocateInfoList(KingAllocateInfoEntity erpKingAllocateInfo) {
        return erpKingAllocateInfoMapper.selectErpKingAllocateInfoList(erpKingAllocateInfo);
    }

    /**
     * 新增new调拨单
     *
     * @param erpKingAllocateInfo new调拨单
     * @return 结果
     */
    @Override
    public AjaxResult insertErpKingAllocateInfo(KingAllocateInfoEntity erpKingAllocateInfo) {

        return AjaxResult.success();
    }

    /**
     * 暂存金蝶-调拨单
     * todo:源单是调拨申请单子，检验明细与申请单的明细是否一致
     *
     * @param kingAllocateInfoEntity
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult draft(KingAllocateInfoEntity kingAllocateInfoEntity) {
        if (CollectionUtils.isEmpty(kingAllocateInfoEntity.getKingAllocateDetailEntityList())) {
            return AjaxResult.error("请添加明细");
        }
        Date nowDate = DateUtils.getNowDate();
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        String id = SnowflakeIdWorker.getInstance().nextStringId();
        kingAllocateInfoEntity.setId(id);
        String companyId = CurrentUserUtil.getCompanyId();
        SysDept sysDept = sysDeptService.getById(companyId);
        int count = this.count();
        String countStr = String.format("%06d", count);
        String firstLetter = ChineseToPinyin.getFirstLetter(sysDept.getDeptName());
        String docNum = firstLetter.concat("_DBD_").concat(countStr);
        kingAllocateInfoEntity.setDocCode(docNum);
        kingAllocateInfoEntity.setCreateBy(userId);
        kingAllocateInfoEntity.setCreateTime(nowDate);
        kingAllocateInfoEntity.setState(ConstUtil.STATE_IN_DRAFT);
        checkKingAllocateDetail(kingAllocateInfoEntity.getKingAllocateDetailEntityList());
        kingAllocateInfoEntity.getKingAllocateDetailEntityList().forEach(s -> {
            s.setId(SnowflakeIdWorker.getInstance().nextStringId());
            s.setAllocateId(id);
            s.setCreateBy(userId);
            s.setCreateTime(nowDate);
            s.setBusinessType(ConstUtil.ALLOCATE_DETAIL__TYPE_STR);
        });
        boolean saved = kingAllocateDetailService.saveBatch(kingAllocateInfoEntity.getKingAllocateDetailEntityList());
        if (!saved) {
            return AjaxResult.error("保存明细失败");
        }
        boolean save = this.save(kingAllocateInfoEntity);
        if (!save) {
            return AjaxResult.error("暂存失败");
        }
        return AjaxResult.success("暂存调拨单成功", id);
    }

    /**
     * 提交金蝶-调拨单
     * @param kingAllocateInfoEntity
     * @return
     */
    @Override
    public AjaxResult submit(KingAllocateInfoEntity kingAllocateInfoEntity) {
        StartProcessDto startDto = new StartProcessDto().
                setBusinessId(kingAllocateInfoEntity.getId()).
                setBusinessType(kingAllocateInfoEntity.getBusinessType()).setModelId(kingAllocateInfoEntity.getModelId()).
                setBusinessName("调拨单".concat(kingAllocateInfoEntity.getId()));
        String instanceId = actModelService.startProcess(startDto);
        kingAllocateInfoEntity.setInstanceId(instanceId);
        kingAllocateInfoEntity.setState(ConstUtil.STATE_IN_PROCESS);
        boolean updated = this.updateById(kingAllocateInfoEntity);
        if (!updated) {
            return AjaxResult.error("提交失败");
        }
        return AjaxResult.success("提交调拨申请单成功");
    }

    /**
     * 审批通过金蝶-调拨单
     * @param kingAllocateInfoEntity
     * @return
     */
    @Override
    public boolean approvedAllocate(KingAllocateInfoEntity kingAllocateInfoEntity) {
        if (ConstUtil.STATE_FINISH.equals(kingAllocateInfoEntity.getState())) {
            List<KingAllocateDetailEntity> detailEntities = kingAllocateDetailService.list(new LambdaQueryWrapper<KingAllocateDetailEntity>()
                    .eq(KingAllocateDetailEntity::getAllocateId, kingAllocateInfoEntity.getId())
                    .eq(KingAllocateDetailEntity::getIsUsed, ConstUtil.IS_USED_YES)
            );
            for (KingAllocateDetailEntity detailEntity : detailEntities){
                KingRealInventoryEntity realInventoryEntity = kingRealInventoryEntityService.getOne(new LambdaQueryWrapper<KingRealInventoryEntity>()
                        .eq(KingRealInventoryEntity::getWarehouseCode, detailEntity.getOutWarehouse())
                        .eq(KingRealInventoryEntity::getWarehousePosition, detailEntity.getOutWarehouseRegion())
                        .eq(KingRealInventoryEntity::getMaterialCode, detailEntity.getMaterialCode()));

                KingRealInventoryEntity inventoryEntity = kingRealInventoryEntityService.getOne(new LambdaQueryWrapper<KingRealInventoryEntity>()
                        .eq(KingRealInventoryEntity::getWarehouseCode, detailEntity.getInWarehouse())
                        .eq(KingRealInventoryEntity::getWarehousePosition, detailEntity.getInWarehouseRegion())
                        .eq(KingRealInventoryEntity::getMaterialCode, detailEntity.getMaterialCode()));
                if (Objects.isNull(realInventoryEntity)){//库存不存在，没法调出审核回滚
                    throw new RuntimeException("库存不存在，没法调出审核回滚");
                }else{
                    //调出的数量
                    BigDecimal outAllocateNum = new BigDecimal(detailEntity.getAllocateNum());
                    realInventoryEntity.setInventoryNum(String.valueOf(new BigDecimal(realInventoryEntity.getInventoryNum()).subtract(outAllocateNum)));
                    //调入的数量
                    BigDecimal inAllocateNum = new BigDecimal(detailEntity.getAllocateNum());
                    inventoryEntity.setInventoryNum(String.valueOf(new BigDecimal(inventoryEntity.getInventoryNum()).add(inAllocateNum)));
                    if (kingRealInventoryEntityService.updateById(realInventoryEntity)){
                        if (kingRealInventoryEntityService.updateById(inventoryEntity)){
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * 修改new调拨单
     *
     * @param erpKingAllocateInfo new调拨单
     * @return 结果
     */
    @Override
    public int updateErpKingAllocateInfo(KingAllocateInfoEntity erpKingAllocateInfo) {
        erpKingAllocateInfo.setUpdateTime(DateUtils.getNowDate());
        return erpKingAllocateInfoMapper.updateErpKingAllocateInfo(erpKingAllocateInfo);
    }

    /**
     * 批量删除new调拨单
     *
     * @param ids 需要删除的new调拨单ID
     * @return 结果
     */
    @Override
    public int deleteErpKingAllocateInfoByIds(String[] ids) {
        return erpKingAllocateInfoMapper.deleteErpKingAllocateInfoByIds(ids);
    }

    /**
     * 删除new调拨单信息
     *
     * @param id new调拨单ID
     * @return 结果
     */
    @Override
    public int deleteErpKingAllocateInfoById(String id) {
        return erpKingAllocateInfoMapper.deleteErpKingAllocateInfoById(id);
    }

    /***
     * 校验明细
     * @param kingAllocateDetailEntityList
     */
    private void checkKingAllocateDetail(List<KingAllocateDetailEntity> kingAllocateDetailEntityList) {
        for (KingAllocateDetailEntity kingAllocateDetailEntity : kingAllocateDetailEntityList) {
            //调拨数量
            String allocateNum = kingAllocateDetailEntity.getAllocateNum();
            KingAllocateDetailEntity detailEntity = kingAllocateDetailService.getById(kingAllocateDetailEntity.getSourceMaterialDetailId());
            //申请单的数量
            String entityAllocateNum = detailEntity.getAllocateNum();
            if (new BigDecimal(allocateNum).compareTo(new BigDecimal(entityAllocateNum)) > 0) {
                throw new RuntimeException("调拨数量不能大于申请单数量");
            }
            //查询已经调拨的申请单的明细
            List<KingAllocateDetailEntity> list = kingAllocateDetailService.list(new LambdaQueryWrapper<KingAllocateDetailEntity>()
                    .eq(KingAllocateDetailEntity::getSourceMaterialDetailId, kingAllocateDetailEntity.getSourceMaterialDetailId()));
            BigDecimal sum = list.stream().map(KingAllocateDetailEntity::getAllocateNum).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add);
            //剩余数量
            BigDecimal surplusNum = new BigDecimal(entityAllocateNum).subtract(sum);
            if (new BigDecimal(allocateNum).compareTo(surplusNum) > 0) {
                throw new RuntimeException("调拨数量不能大于剩余数量");
            }

        }
    }
}
